/*********************************************************************\
*
*                  (c) lkc
*                  All Rights Reserved. lkc Confidential
*
\*********************************************************************/
/*********************************************************************\
*   Title                      :
*
*   Module Description         :
*
*   Author                     : lkc
*
*   Created                    : 2018-7-24
*
\*********************************************************************/

#include "ProtocolMCU.h"
#ifdef MCU_IS_ALIVE
#include <math.h>
#include "CamGainControl.h"
#include "UtilityTH.h"

const float ICCD_CATHODE_RADIUS = 9.0;
const double RADIAN = 57.29577951;

ProtocolMCU ProtocolMCU::m_Instance;

void ProtocolMCU::DefaultSend()
{
    m_header1Send = HEAD1;
    m_header2Send = HEAD2_EVENT;
    m_dataSend = 0x00;
    m_endSend = END;
}

void ProtocolMCU::BuildFrame()
{
    m_frameToSend[0] = m_header1Send;
    m_frameToSend[1] = m_header2Send;
    m_frameToSend[2] = m_funcCodeSend;
    m_frameToSend[3] = m_commandSend;
    m_frameToSend[4] = m_dataSend;
    m_frameToSend[5] = CheckSum(&m_frameToSend[2],3);
    m_frameToSend[6] = m_endSend;
}

int ProtocolMCU::SendFrame()
{
    BuildFrame();
    int ret = Send(m_frameToSend,FRAME_LENGTH_EVENT_SEND);
    if(ret<0)
    {
        qDebug()<<"ProtocolMCU send error\n";
    }
    else
    {
//        printf("data send to MCU: ");
//        for(int i = 0;i< ret;i++)
//        {
//            printf("%#X ", m_frameToSend[i] );
//        }
//        printf("\n");
    }
    return ret;
}

void ProtocolMCU::MotoSelfCheck(ReportFocusCtlDelegate *ptr)
{
    m_reportDelegate = ptr;
    m_selfCheckState = true;
//    m_selfCheckResult = true;
    DefaultSend();
    m_funcCodeSend = 0xC0;
    m_commandSend =0x01;
    m_dataSend = 0x00;
    SendFrame();
}

void ProtocolMCU::MotoSelfCheck()
{
    MotoSelfCheck(nullptr);
}


void ProtocolMCU::FocusDefaultSend()
{
    DefaultSend();
    m_funcCodeSend = 0xC1;
}

void ProtocolMCU::IncFocus(ReportFocusCtlDelegate *ptr, unsigned char step)//增大相机焦距，步长step，最大150
{
    m_reportDelegate = ptr;
    FocusDefaultSend();
    m_commandSend =0x01;
    m_dataSend = step;
    SendFrame();
}

void ProtocolMCU::IncFocus(unsigned char step)//增大相机焦距，步长step，最大150
{
    IncFocus(nullptr,step);
}

void ProtocolMCU::DecFocus(ReportFocusCtlDelegate *ptr, unsigned char step)//减小相机焦距，步长step，最小50
{
    m_reportDelegate = ptr;
    FocusDefaultSend();
    m_commandSend =0x02;
    m_dataSend = step;
    SendFrame();
}

void ProtocolMCU::DecFocus(unsigned char step)//减小相机焦距，步长step，最小50
{
    DecFocus(nullptr,step);
}

void ProtocolMCU::SetFocus(unsigned char value, ReportFocusCtlDelegate *ptr)//设置相机焦距，范围50～150
{
    m_reportDelegate = ptr;
    FocusDefaultSend();
    m_commandSend =0x03;
    m_dataSend = value;
    SendFrame();
}

void ProtocolMCU::SetFocus(unsigned char value)//设置相机焦距，范围50～150
{
    SetFocus(value,nullptr);
}

void ProtocolMCU::SetView(float value)
{
    unsigned char focus = ICCD_CATHODE_RADIUS/tan(value/RADIAN/2.0);
//    if(dataFo>150)
//    {
//        dataFo = 150;
//    }
//    else if(dataFo<50)
//    {
//        dataFo = 50;
//    }
    SetFocus(focus);
}

void ProtocolMCU::GetFocusCommand()
{
    FocusDefaultSend();
    m_commandSend =0x04;
    m_dataSend = 0;
    SendFrame();
}

unsigned char ProtocolMCU::GetFocus()
{
    return m_focusNow;
}

float ProtocolMCU::GetViewField()
{
    if(m_focusNow>0)
    {
        return 2*atan(ICCD_CATHODE_RADIUS/m_focusNow)*RADIAN;
    }
    else
    {
        return 6.9;
    }
}

void ProtocolMCU::SetWorkMode(bool mode)
{
    DefaultSend();
    m_funcCodeSend = 0xC2;
    m_commandSend = mode?0x01:0x02;
    m_dataSend = 0x00;
    SendFrame();
}

bool ProtocolMCU::GetSelfCheckState()
{
    return m_selfCheckState;
}

void ProtocolMCU::ExtractData(const unsigned char* data, int nLength)
{
//    printf("data from MCU: ");
//    for(int i = 0;i< nLength;i++)
//    {
//        printf("%#X ", data[i] );
//    }
//    printf("\n");

    bufferTemp.insert(bufferTemp.end(),data,data+nLength);

    while( bufferTemp.size() >= FRAME_LENGTH_CYCLE_RECEIVE)
    {
        auto iter = bufferTemp.begin();
        if (*iter != HEAD1)
            {
                //如果数据开始不是头，则删除数据
                bufferTemp.erase(iter);
                continue;
            }
        if (*(iter+1) == HEAD2_EVENT)
        {
            if(bufferTemp.size() < FRAME_LENGTH_EVENT_RECEIVE)
            {
                break;
            }
            if(*(iter+FRAME_LENGTH_EVENT_RECEIVE-1) != END)
            {
                bufferTemp.erase(iter,iter+2);
                continue;
            }
            unsigned char sum = CheckSum(iter+2,4);
            if(*(iter+FRAME_LENGTH_EVENT_RECEIVE-2) != sum)
            {
                bufferTemp.erase(iter,iter+2);
                continue;
            }
            //到此，找到一帧完整的数据
            EventReceiveFrameParse();
            bufferTemp.erase(iter,iter+FRAME_LENGTH_EVENT_RECEIVE);
        }
        else if(*(iter+1) == HEAD2_CYCLE)
        {
            if(*(iter+FRAME_LENGTH_CYCLE_RECEIVE-1) != END)
            {
                bufferTemp.erase(iter,iter+2);
                continue;
            }
            //到此，找到一帧完整的数据
            CycleReceiveFrameParse();
            bufferTemp.erase(iter,iter+FRAME_LENGTH_CYCLE_RECEIVE);
        }
        else
        {
            bufferTemp.erase(iter);
        }
    }
}

int ProtocolMCU::CycleSendOnce()
{
    GetFocusCommand();
    return 1;
}

void ProtocolMCU::EventReceiveFrameParse()
{
    m_funcCodeReceive = bufferTemp[2];
    m_commandReceive = bufferTemp[3];
    m_dataReceive = bufferTemp[4];
    m_resultReceive = bufferTemp[5];
    m_result = (m_resultReceive == SUCCESS);
    switch (m_funcCodeReceive)
    {
    case 0xC0:
        SelfCheckParse();
        break;
    case 0xC1:
        FoucsParse();       
        break;
    case 0xC2:
        WorkModeParse();
        break;
    default:
        break;
    }
}

void ProtocolMCU::CycleReceiveFrameParse()
{
    FocusNowConfirm(bufferTemp[2]);
//    m_focusNow = bufferTemp[2];
}

void ProtocolMCU::SelfCheckParse()
{
    if(m_commandReceive == 0x01)//启动相机自检
    {
//        if(m_resultReceive == SUCCESS)
//        {
////            m_selfCheckResult = true;
//        }
//        else if(m_resultReceive == FAIL)
//        {
////            m_selfCheckResult = false;
//        }
//        m_selfCheckState = false;
    }
    m_selfCheckState = m_result;
    ReportSelfCheck(m_result);
}

void ProtocolMCU::FoucsParse()
{
    FocusNowConfirm(m_dataReceive);
    switch(m_commandReceive)
    {
    case 0x01://增加焦距
        ReportFocusInc(m_result);
        break;
    case 0x02://减小焦距
        ReportFocusDec(m_result);
        break;
    case 0x03://设置焦距绝对值
        ReportFocusSet(m_result);
        break;
    default:
        break;
    }
}

void ProtocolMCU::WorkModeParse()
{
    switch(m_commandReceive)
    {
    case 0x01://工作模式
        break;
    case 0x02://待机模式
        break;
    default:
        break;
    }
}

void ProtocolMCU::FocusNowConfirm(unsigned char focus)
{
    unsigned char focusLocal = focus;
    if(focusLocal>FOCUS_MAX)
    {
        focusLocal = FOCUS_MAX;
    }
    else if(focusLocal<FOCUS_MIN)
    {
        focusLocal = FOCUS_MIN;
    }
    m_focusMtx.lock();
    m_focusNow = focusLocal;
    m_focusMtx.unlock();
}

void ProtocolMCU::ReportSelfCheck(bool result)
{
    if(m_reportDelegate==nullptr)
    {
        return;
    }
    m_reportDelegate->ReportStartSelfCheck(result);
}

void ProtocolMCU::ReportFocusInc(bool result)
{
    if(m_reportDelegate==nullptr)
    {
        return;
    }
    m_reportDelegate->ReportFocusInc(result);
}

void ProtocolMCU::ReportFocusDec(bool result)
{
    if(m_reportDelegate==nullptr)
    {
        return;
    }
    m_reportDelegate->ReportFocusDec(result);
}

void ProtocolMCU::ReportFocusSet(bool result)
{
    if(m_reportDelegate==nullptr)
    {
        return;
    }
    m_reportDelegate->ReportFocusSet(result);
}
#endif //#ifdef MCU_IS_ALIVE

/********************************************************************\
 *
 * REVISION RECORDS
 *
\*********************************************************************/
/*********************************************************************/
/*
 *
 *
 *
\*********************************************************************/
/*------------------------------The End------------------------------*/
